@namespace WtmBlazorUtils
@inherits WTComponent
@inject WtmBlazorContext WtmBlazor
@using System.Threading;
@using System.Linq.Expressions;
@using System.IO;
@typeparam TValue

<div>
    @if (dlist != null)
    {
        <AvatarUpload @ref="uploader" Value="Value" ValueExpression="ValueExpression" ValueChanged="ValueChanged" Accept="image/*" IsSingle="!IsMultiple" ShowProgress="true" OnChange="@OnAvatarUpload"
                      OnDelete="@OnAvatarDelete" DisplayText="@LabelText" DefaultFileList="@dlist" IsDisabled="@IsDisabled"></AvatarUpload>
    }
</div>
@code{

    [Parameter]
    public int? ThumbWidth { get; set; } = 200;
    [Parameter]
    public int? ThumbHeight { get; set; } = 200;
    [Parameter]
    public TValue Value { get; set; }
    [Parameter]
    public EventCallback<TValue> ValueChanged { get; set; }
    [Parameter]
    public Expression<Func<TValue>> ValueExpression { get; set; }
    [Parameter]
    public bool IsDisabled { get; set; }

    private bool IsMultiple
    {
        get
        {
            if (typeof(IEnumerable<ISubFile>).IsAssignableFrom(typeof(TValue)))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
    [Parameter]
    public bool ShowLabel { get; set; } = true;
    [Parameter]
    public string LabelText { get; set; } = null;

    private Dictionary<string, string> files { get; set; } = new Dictionary<string, string>();
    private List<UploadFile> dlist = null;
    private AvatarUpload<TValue> uploader { get; set; }
    private bool FileSet { get; set; } = false;

    protected TValue CurrentValue
    {
        get => Value;
        set
        {
            var hasChanged = !EqualityComparer<TValue>.Default.Equals(value, Value);
            if (hasChanged)
            {
                Value = value;
                _ = ValueChanged.InvokeAsync(value);
            }
        }
    }

    protected override async Task OnInitializedAsync()
    {

        if (Value != null)
        {
            List<UploadFile> temp = new List<UploadFile>();
            if (IsMultiple == false)
            {
                var rv = await WtmBlazor.Api.CallAPI<byte[]>($"/api/_file/GetFile/{Value}", HttpMethodEnum.GET, new Dictionary<string, string> {
                    {"width", ThumbWidth?.ToString() },
                    {"height", ThumbHeight?.ToString() }
                });
                if (rv.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    temp.Add(new UploadFile
                    {
                        PrevUrl = $"data:image/jpeg;base64,{Convert.ToBase64String(rv.Data)}",
                        FileName = Value.ToString()
                    }); ;
                    files.Add(Value.ToString(), Value.ToString());
                }
                else
                {
                    Guid? ng = null;
                    CurrentValue = (TValue)(object)ng;
                }
                dlist = temp;
            }
            else
            {
                var list = Value as IEnumerable<ISubFile>;
                foreach (var item in list)
                {
                    var rv = await WtmBlazor.Api.CallAPI<byte[]>($"/api/_file/GetFile/{item.FileId}", HttpMethodEnum.GET, new Dictionary<string, string> {
                    {"width", ThumbWidth?.ToString() },
                    {"height", ThumbHeight?.ToString() }
                });
                    if (rv.StatusCode == System.Net.HttpStatusCode.OK)
                    {
                        temp.Add(new UploadFile
                        {
                            PrevUrl = $"data:image/jpeg;base64,{Convert.ToBase64String(rv.Data)}",
                            FileName = item.FileId.ToString()
                        });
                        files.Add(item.FileId.ToString(), item.FileId.ToString());
                    }
                }
                dlist = temp;
            }
        }
        else
        {
            dlist = new List<UploadFile>();
        }
        ClearDeletedIds();
        await base.OnInitializedAsync();
    }


    private async Task OnAvatarUpload(UploadFile file)
    {
        bool suc = false;
        if (file != null && file.File != null)
        {
            var format = file.File.ContentType;
            if (CheckValidAvatarFormat(format))
            {

                byte[] filedata = await GetFileData(file.File);
                var rv = await WtmBlazor.Api.CallAPI<DynamicData>("/api/_file/UploadImage", HttpMethodEnum.POST, new Dictionary<string, string> {
                    {"width", ThumbWidth?.ToString() },
                    {"height", ThumbHeight?.ToString() }
                }, filedata, file.File.Name);
                if (rv.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    files.Add(rv.Data.Fields["Id"].ToString(), file.File.Name);
                    if (IsMultiple)
                    {
                        CurrentValue = (TValue)PropertyHelper.MakeList(typeof(TValue).GetGenericArguments()[0], "FileId", files.Select(x => x.Key).ToArray());
                    }
                    else
                    {
                        CurrentValue = (TValue)(object)(new Guid(files.First().Key));
                    }
                    suc = true;
                }


                await file.RequestBase64ImageFileAsync(format, 400, 300);
            }

        }
        if (suc == false)
        {
            await WtmBlazor.Toast.Error(WtmBlazor.Localizer["Sys.Error"],WtmBlazor.Localizer["Sys.UploadFailed"]);
        }

    }

    private async Task<bool> OnAvatarDelete(UploadFile file)
    {

        var idstr = files.Where(x => x.Value == file.OriginFileName || x.Key == file.FileName).Select(x => x.Key).FirstOrDefault();
        if (idstr != null)
        {
            var rv = await WtmBlazor.Api.CallAPI($"/api/_file/DeletedFile/{idstr}");
            files.Remove(idstr);
            SetDeletedIds(idstr);
            if (IsMultiple == true)
            {
                CurrentValue = (TValue)PropertyHelper.MakeList(typeof(TValue).GetGenericArguments()[0], "FileId", files.Select(x => x.Key).ToArray());
            }
            else
            {
                Guid? ng = null;
                CurrentValue = (TValue)(object)ng;
            }
        }
        return true;
    }

    private bool CheckValidAvatarFormat(string format)
    {
        return "jpg;png;bmp;gif;jpeg".Split(';').Any(f => format.Contains(f, StringComparison.OrdinalIgnoreCase));
    }

    private async Task<byte[]> GetFileData(IBrowserFile file)
    {
        using var fileStream = file.OpenReadStream(WtmBlazor.ConfigInfo.FileUploadOptions.UploadLimit);
        using var memoryStream = new MemoryStream();
        await fileStream.CopyToAsync(memoryStream);
        byte[] rv = memoryStream.ToArray();
        memoryStream.Dispose();
        fileStream.Dispose();
        return rv;
    }

    private void SetDeletedIds(string id)
    {
        var refpage = PropertyHelper.GetExpressionRootObj(ValueExpression) as BasePage;
        if(refpage != null)
        {
            if(string.IsNullOrEmpty(id) == false)
            {
                if(refpage.DeletedFileIds == null)
                {
                    refpage.DeletedFileIds = new List<string>();
                }
                if (refpage.DeletedFileIds.Contains(id) == false)
                {
                    refpage.DeletedFileIds.Add(id);
                }
            }
        }
    }

    private void ClearDeletedIds()
    {
        var refpage = PropertyHelper.GetExpressionRootObj(ValueExpression) as BasePage;
        if (refpage != null)
        {
            refpage.DeletedFileIds = new List<string>();
        }
    }

}
